package com.aliware.tianchi;

import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

public class ProviderManager{
    public static List<Bucket> getBuckets() {
        return buckets;
    }
    private static List<Bucket>  buckets = new ArrayList<>();
    private static int tick = 0;
    public static AtomicInteger max = new AtomicInteger(80);
    public static Queue<AvgTime> getQueue() {
        return queue;
    }
    private static Queue<AvgTime> queue = new ConcurrentLinkedQueue<>();
    public static AtomicLong getTotalTime() {
        return totalTime;
    }
    private static AtomicLong totalTime = new AtomicLong(0);
    private static AtomicLong successCountPerSecond = new AtomicLong(0);
    private static AtomicLong bestSuccessCountPerSecond = new AtomicLong(0);
    private static AtomicInteger bestConcurrency = new AtomicInteger(0);
    public static AtomicLong getSuccessCountPerSecond() {
        return successCountPerSecond;
    }
    private static Integer delta = 6;
    public static final Integer BUCKETNUM = 7;
    static {
        for (int i = 0; i < BUCKETNUM; i++) {
            buckets.add(new Bucket());
        }
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                ProviderManager.resetTime();
                tick++;
                if(tick <= 50){
                    if(bestSuccessCountPerSecond.get()<successCountPerSecond.get()){
                        bestSuccessCountPerSecond.set(successCountPerSecond.get());
                        bestConcurrency.set(max.get());
                        //System.out.println("bestSuccessCountPerSecond:  " + bestSuccessCountPerSecond.get() + "  bestConcurrency:" +bestConcurrency.get());
                    }
                    if(bestSuccessCountPerSecond.get()-50>=successCountPerSecond.get()){
                        max.addAndGet(-1 * delta);
                        //delta --;
                    }
                    max.addAndGet(delta);
                    successCountPerSecond.set(0);
                }
                if (tick >= 51 && tick <= 60) {
                    max.set(bestConcurrency.get());
                }
            }
        }, 1000, 1100);
    }
    // provider信息
    private static final ProviderInfo SERVER_INFO = new ProviderInfo();

    public static ProviderInfo getServerInfo() {
        return SERVER_INFO;
    }

    public static void endTime(long expend, boolean succeeded) {
        long now = System.currentTimeMillis();
        totalTime.addAndGet(expend);
        Long activate = SERVER_INFO.getAllActiveCount().get();
        int index = (int) (activate / 50);
        if (index > BUCKETNUM-1) {
            index = BUCKETNUM-1;
        }
        if (expend <= 200) {
            buckets.get(index).getAtomicLongArray().incrementAndGet((int)expend );
            buckets.get(index).getCount().incrementAndGet();
        } else {
            buckets.get(index).getAtomicLongArray().incrementAndGet(199);
            buckets.get(index).getCount().incrementAndGet();
        }
        queue.offer(new AvgTime(expend, now, activate));
        while (true) {
            assert queue.peek() != null;
            if (!(queue.peek().getTime() < now - 100)) break;
            AvgTime avgTime = queue.poll();
            assert avgTime != null;
            Long act = avgTime.getConcurrency();
            int i = (int) (act / 50);
            totalTime.addAndGet(-avgTime.getExpand());
            long j =  avgTime.getExpand();
            if (avgTime.getExpand() <= 100) {
                buckets.get(i).getAtomicLongArray().decrementAndGet((int)j);
                buckets.get(i).getCount().decrementAndGet();
            } else {
                buckets.get(i).getAtomicLongArray().decrementAndGet(199);
                buckets.get(i).getCount().decrementAndGet();
            }
        }
        SERVER_INFO.getAllActiveCount().decrementAndGet();
        SERVER_INFO.getAllReqCount().incrementAndGet();
        SERVER_INFO.getAllSpendTimeTotal().addAndGet(expend);
    }

    public static void resetTime() {
        SERVER_INFO.getAllSpendTimeTotal().set(0L);
        SERVER_INFO.getAllReqCount().set(0L);
    }

    public static void startTime() {
        SERVER_INFO.getAllActiveCount().incrementAndGet();
    }
}
